;------------------------------------------------------------------------------- ; ; Ucode for KENNEDY or PERTEC formatter and DMA tape controller. ; ;------------------------------------------------------------------------------- .REPEAT XUCODE [ .USE[HIGHMEM] ;If 8K u-mem present, put tape code there. ] ;TAPE READING AND WRITING CODE ; A-MEM USEAGE: ; 0 DISPATCH ADDR. TPMODE = 0 ;DATA PACKING MODE ; BIT 0: 0=PDP-10 CORE-DUMP, 1=INDUSTRY (32-bit mode) ; BIT 1: NRZI Kluge Mode (to read old CCRMA & SCI tapes) ; 1 Used by FMNBWT and TRCHECK for NRZI Kluge Mode info. ; 2 Used by KNYGOA and TRCHECK for NRZI Kluge Mode info. ; 3 DON'T USE... Storing into it clobbers IR left ! ; 4 Next mem adr of xfer (STRTDC) -- 0 during non-data ops ; 5 Remaining word count in current WCMA (STRTDC) ; 6 Not currently used-- will be Data Channel PC ; 7 RETRY COUNT (WRITE); 400000,,STARTING-MA (READ) ;MAPF values TP.RS = 4 ;read status (from formatter) TP.RC = 2 ;read control (controller status and un-fifo'd read data) TP.WF = 2 ;write formatter (send ctrl bits to formatter) TP.WM = 4 ;write mode control reg. TP.WC = 1 ;write control reg. TP.MR = 5 ;give Master Reset TP.WMA = 3 ;write (load) the CNTMA reg. (count and MA) KNYCLR: ;RESET the formatter and drive. KNYRS1: START-OUT ALU[0] DEST[IOD] $ ;Turn off "FORMATTER ENABLE" MAPF[TP.WF] LONG POPJ $ ;725 - OBSOLETE VERSION OF READ .PAIR UIOTRP[MUUO] $ TAPERD: D[CONST 14] ROT[6] DEST[IR-ADR] NORM PUSHJ[KNYRGO] $ ;Fake a word count of 1400 D[MA] DEST[4] DEST-A-MEM NORM PUSHJ[TRP2] $ ALU[Q] DEST[AC] ACSEL[AC] NORM JUMP[GOMAIN] $ ;Move status into AC. ; KNYRGO -- Called to start tape motion on reads. KNYRGO: NORM PUSHJ[DCINIT] $ ;Init the data channel. D[10 + TPMODE] ROT[1] MASK[1] DEST[AR] NORM $ ;Get the 32-bit mode flag. START-OUT D[AR] ROT[35. - 29.] DEST[IOD] NORM $ ;Position it for the hardware. MAPF[TP.WM] D[CONST 0] DEST[Q] C-OUT JUMP[KNYGOA] $ ;Send command to formatter. ;Send a tape-motion command to the formatter. Call with command bits ; (except for FMTR ENABLE and GO) in Q. Clobbers Q, HOLD, AR KNYGOA: START-IN D[CONST 1] ROT[35. - 26.] ALU[DORQ] DEST[Q] PUSHJ[FMNBWT] $ ;Add the FMTR ENBL bit to the command word. ;Wait for FORMATTER NOT BUSY. D[MEM] DEST[2] DEST-A-MEM NORM $ ;Save status bits returned by FMNBWT for use by TRCHECK START-OUT D[CONST 1] ROT[35. - 33.] ALU[D#Q] DEST[IOD] C-OUT $ ;Set the GO bit to fmtr (except: on RWD, CLEAR the bit !) MAPF[TP.WF] START-OUT D[CONST 1] ROT[35. - 33.] ALU[-D&Q] DEST[IOD] $ ;Send command word again, without GO bit. MAPF[TP.WF] LONG POPJ $ FMNBWT: ;Wait for formatter to be not busy. ;Return tape status in MEM; timeout in 164 msec. ;Duration of loop should be 10 usec. (for TRCHECK). START-IN D[CONST 1] ROT[14.] DEST[AR] NORM $ FMNBW1: MAPF[TP.RS] D[IOD] DEST[HOLD] C800 $ ;GET STATUS BITS. D[AR] ALU[D-1] DEST[AR] C550 OBUS<0 JPOP[FMTHNG] $ D[CONST 14.] LLOAD C600 $ C500 LOOP[.] $ ;We execute this instr. 15. times, for a 7.5 usec delay. START-IN D[MEM] ROT[7] C550 -OBUS<0 JUMP[FMNBW1] $ ;check for 'BUSY' D[AR] DEST[1] DEST-A-MEM NORM POPJ $ ;Save ending timeout count (for TRCHECK) FMTHNG: NORM PUSHJ[KNYRS1] $ ;Blast the formatter. D[CONST 42] ROT[30.] DEST[AC] JPOP[GOMAIN] $ ;Return error code for 'hung fmtr' and abort. NCNTWT: ;Wait for TP CNT GO to be off. ;Return tape status in MEM; timeout in 164 msec. ;Duration of loop should be 10 usec. (for TRCHECK). NCNTW1: MAPF[TP.RC] D[IOD] DEST[HOLD] C800 $ ;GET STATUS BITS. D[AR] ALU[D-1] DEST[AR] C550 OBUS<0 POPJ $ ;Exit if we time out-- probably just a short record. D[CONST 14.] LLOAD C600 $ C500 LOOP[.] $ ;We execute this instr. 15. times, for a 7.5 usec delay. START-IN D[MEM] ROT[19.] C550 OBUS<0 JUMP[NCNTW1] $ ;check for not TP CNT GO D[AR] DEST[1] DEST-A-MEM NORM POPJ $ ;Save ending timeout count (for TRCHECK) ;INITIALIZE DATA CHANNEL DCINIT: START-OUT D[CONST 8.] LLOAD NORM $ ;Give TP MR MAPF[TP.MR] START-OUT ALU[0] DEST[IOD] C600 $ ;Load 0 into cntma (the COUNT and MA registers) MAPF[TP.WMA] START-OUT D[MASK 12.] ROT[35. - 13.] DEST[IOD] C600 $ ;Load cntma again-- since COUNT is currently 0, this will ; force BUF CNT to be 0. But, we put -1 into COUNT this ; time, which, with BUF CNT = 0, will make BUF CNT load ; properly when STARTDC loads cntma. MAPF[TP.WMA] START-OUT D[CONST 2] DEST[IOD] C600 $ ;Set MBUSY MAPF[TP.WC] C550 LOOP[.] $ ;Wait for a few usec. This clears mem rq. START-OUT ALU[0] DEST[IOD] NORM $ ;Clr MBUSY MAPF[TP.WC] C600 POPJ $ ;START DATA CHANNEL to write or read a record. Transfer up to C(IR-ADR) words; ; starting address is in A-MEM[4]. STRTDC: D[IR] MASK[18.] NORM DEST[5] DEST-A-MEM $ ;Initialize word count D[CONST 1] ROT[14.] DEST[1] DEST-A-MEM NORM $ ;Initialize timeout count (for NCNTWT and FMNBWT) STDC1: MAPF[0] C600 PUSHJ[DCGO] $ ;start xfer -- MAPF is relevant if we looped back here on READ MAPF[0] START-IN D[11] DEST[AR] C600 PUSHJ[NCNTW1] $ ;Wait for TP CNT GO to be off (continue with current timeout count) ;MAPF is relevant if we came from DCGWR below. D[17] C550 -OBUS<0 JUMP[STDC1] $ ;Jump if this is a WRITE operation. START-OUT D[AR] C550 -OBUS<0 JUMP[STDC1] $ ;READ op, so set MEM RQ to store last word. ;Jump unless we timed out waiting for end of last COUNT. WCDONE: MAPF[0] START-IN D[11] DEST[AR] C600 JUMP[FMNBW1] $ ;Enter FMNBWT with the timeout count left from NCNTWT. ;The MAPF sets MEM RQ if we have fallen in from previous instr. DCGO: D[15] DEST[Q AR HOLD] C550 OBUS=0 JPOP[WCDONE] $ ;Get remaining word count. If =0, we are done. D[CONST 14] ROT[6] ALU[Q-D] C550 OBUS<0 JUMP[DCG1] $ ;Jump if it is less than 1400 D[CONST 14] ROT[6] DEST[Q AR] NORM $ ;It is not. Use 1400 instead. DCG1: D[MEM] ALU[D-Q] DEST[5] DEST-A-MEM NORM $ ;Decrement remaining WC by amount of current WC. D[14] DEST[HOLD] SHORT $ ;Get current starting adr D[MEM] ALU[D+Q] DEST[4] DEST-A-MEM NORM $ ;Increment it by current WC. D[10 + TPMODE] C550 OBUS<0 JUMP[. + 2] $ ;Are we in 32-bit mode ? Jump if so. D[AR] ROT[2] ALU[D+Q] DEST[AR] NORM JUMP[. + 2] $ ;Form byte count (=5*word count). D[AR] ROT[2] ALU[D] DEST[AR] NORM $ ;Form byte count (=4*word count). D[AR] ALU[D-1] DEST[AR] NORM $ ;Adjust count to be right for hdwr. D[AR] ROT[35. - 13.] DEST[Q] NORM $ ;Align count at bit 13. START-OUT D[MEM] MASK[20.] ALU[DORQ] DEST[IOD] NORM $ ;Include mem addr and load into COUNT, MA ;Also sets BUF CNT to 0 (if IN) or 5 (if OUT)-- this ; depends on COUNT not =0 and BUF CNT not = 4 or 5 MAPF[TP.WMA] START-OUT D[CONST 2] DEST[IOD] C600 $ ;Set M BUSY MAPF[TP.WC] START-OUT C600 $ ;Set CNT GO MAPF[13] D[17] C600 OBUS<0 POPJ $ ;Return if this is a READ op. DCGWR: START-OUT D[15] C550 -OBUS=0 POPJ $ ;Set MEM RQ to fetch first word. ;Return unless this is the last WCMA in the record. MAPF[0] START-OUT D[CONST 12] DEST[IOD] C600 $ ;Last one. Set TP ENB LAST BYTE as well as M BUSY MAPF[TP.WC] C600 POPJ $ ;Here to do the data xfer for a read operation. TRP2: D[14] DEST[Q] SHORT $ ;We must save initial mem. adr. for NRZI KLUGE stuff.. D[CONST 1] ROT[35.] ALU[DORQ] DEST[7] DEST-A-MEM NORM PUSHJ[STRTDC] $ ;Flag op. as a READ, start the data channel JUMP[TRCHKB] $ TRCHECK: PUSHJ[FMNBWT] $ ;wait for formatter not busy. TRCHKB: D[MEM] ROT[32.] C550 -OBUS<0 JUMP[TRERR] $ ;check for hard error status. TRCHA: D[MEM] ROT[33.] C550 -OBUS<0 JUMP[TREOF] $ ;Jump if EOF seen by formatter ALU[0] DEST[Q] NORM $ ;Flag no errors. TRDONE: START-IN NORM $ MAPF[TP.RC] START-IN D[IOD] DEST[AR] C600 $ ;Get data channel status bits. MAPF[3] D[IOD] MASK[21.] ALU[DORQ] DEST[Q 5] DEST-A-MEM C800 $ ;Include ending MA value in status info. D[AR] ROT[19.] C550 -OBUS<0 JUMP[TPMAOK] $ ;If TP CNT GO is off, START-IN D[AR] ROT[24.] MASK[3] ALU[D-1] C550 -OBUS=0 JUMP[TPMAOK] $ ; or if BUF CNT is not =1, then right no. of words were stored. ALU[Q-1] DEST[Q 5] DEST-A-MEM NORM $ ;Otherwise, 1 extra word was stored, so decrement ending MA. TPMAOK: D[MEM] ROT[6] C550 OBUS<0 JUMP[TRCRET] $ ;Done if not in NRZI mode. D[10 + TPMODE] ROT[1] C550 -OBUS<0 JUMP[TRCRET] $ ;Also done if not in NRZI Kluge Mode, D[14] C550 OBUS=0 JUMP[TRCRET] $ ; or if this was not a data-xfer operation. D[12] ROT[12.] C550 -OBUS<0 JUMP[TRCRET] $ ;Neither do we check for EOF if we started at BOT (see KNYGOA) ;In NRZI Kluge Mode, detect EOF by timing. D[17] MASK[20.] ALU[Q-D] DEST[Q HOLD] NORM $ ;Get number of words xferred (= ending MA minus starting MA ) D[MEM] ROT[2] ALU[D+Q] DEST[Q] NORM $ ;Get no. of bytes (=5* no. of words) D[11] MASK[20.] ALU[D+Q] DEST[Q] NORM $ ;Add remaining timeout count from FMNBWT D[CONST 1] ROT[14.] ALU[D-Q] DEST[Q] NORM $ ;Get no. of byte-times not accounted for by bytes xfrd. .REPEAT 1 - 75IPS [ D[CONST 11] ROT[6.] ALU[D-Q] C550 COND[-OBUS18] JUMP[TRCRET] $ ] .REPEAT 75IPS [ D[CONST 15] ROT[6.] ALU[D-Q] C550 COND[-OBUS18] JUMP[TRCRET] $ ] ;Jump if it is not more than appropriate for a record gap. NORM PUSHJ[TAPEBR] $ ;Too long. Assume an EOF was passed. Back up over record read. PUSHJ[FMNBWT] $ D[CONST 60] ROT[30.] DEST[Q] NORM POPJ $ ;Return EOF status. TRCRET: D[14] MASK[18.] ALU[D-1] DEST[Q] C550 OBUS<0 JUMP[TRCX] $ ;Get last loc. of input buffer (<0 iff non-data xfer operation) ALU[0] DEST[HOLD] NORM $ ;Prepare to clear the part of the input buffer we didn't use. .REPEAT NEWMAP [ ALU[-1] DEST[MAP-DISABLE] NORM $ ;Disable mapping. ] .REPEAT 1 - NEWMAP [ START-IN D[CONST 1] DEST[DEV-ADR] NORM $ D[IOD] MASK[3] DEST[IR-ADR] MAPF[4] CYLEN[IOB-IN] $ ALU[0] DEST[DEV-ADR] SHORT $ D[IR] MASK[2] DEST[IOD] SPEC[IOB-OUT] NORM $ MAPF[10] D[CONST 7] DEST[DEV-ADR] C800 $ ] D[15] ALU[D-1] DEST[MA] NORM $ D[MA] ALU[Q-D-1] C550 OBUS<0 JUMP[. + 2] $ D[MA] ALU[D+1] DEST[MA STRT-WRT] NORM JUMP[. - 1] $ .REPEAT NEWMAP [ ALU[0] DEST[MAP-DISABLE] NORM $ ;Enable mapping. ] .REPEAT 1 - NEWMAP [ D[IR] MASK[3] DEST[IOD] NORM $ ALU[0] DEST[DEV-ADR] SPEC[IOB-OUT] NORM $ MAPF[10] D[CONST 7] DEST[DEV-ADR] C800 $ ] TRCX: D[15] DEST[Q] NORM POPJ $ ;Recover ending status and return. TREOF: D[CONST 60] ROT[30.] DEST[Q] NORM JUMP[TRDONE] $ TRERR: D[MEM] ROT[6] C550 OBUS<0 JUMP[. + 2] $ ;Always check hard error if not in NRZI mode. D[10 + TPMODE] ROT[1] C550 OBUS<0 JUMP[TRCHA] $ ;If NRZI, don't check if in kluge mode. D[CONST 50] ROT[30.] DEST[Q] NORM JUMP[TRDONE] $ ;Flag hard read error to progm. .PAIR UIOTRP[MUUO] $ TAPEMT: ;OPCODE 726 -- MTAPE FUNCTIONS. NORM PUSHJ[. + 2] $ NORM JUMP[GOMAIN] $ D[MA] DEST[Q] COND[OBUS=0] JUMP[TAPERW] C550 $ D[CONST 1] ALU[D-Q] COND[OBUS=0] PUSHJ[TWREOF] C550 $ D[CONST 13] ALU[D-Q] COND[OBUS=0] PUSHJ[TERASE] C550 $ D[CONST 50] ALU[D-Q] COND[OBUS=0] JUMP[TPSETIND] C550 $ ;Code ?, set industry compatable mode. D[CONST 51] ALU[D-Q] COND[OBUS=0] JUMP[TPSETDMP] C550 $ ;Code ?, set PDP-10 dump mode. D[CONST 60] ALU[D-Q] COND[OBUS=0] JUMP[TPSETNK] C550 $ ;Code ?, set NRZI KLUGE mode. D[CONST 61] ALU[D-Q] COND[OBUS=0] JUMP[TPCLRNK] C550 $ ;Code ?, clear NRZI KLUGE mode. D[CONST 5] ALU[D-Q] COND[OBUS=0] PUSHJ[TAPEFR] C550 $ D[CONST 6] ALU[D-Q] COND[OBUS=0] PUSHJ[TAPEBR] C550 $ ALU[0] DEST[4] DEST-A-MEM NORM PUSHJ[TRCHECK] $ ;Wait for op. to finish and get ending status in Q. ; The 0 in A-MEM[4] prevents TRCHECK from clearing read buf ! ALU[Q] DEST[AC] NORM JPOP[GOMAIN] $ ;Return status to caller in his AC (same as READ) TWREOF: ;WRITE AN END OF FILE (TAPE MARK) D[CONST 1] ROT[35. - 28.] DEST[Q] NORM $ ;Get WFM (WRITE EOF) cmd bit for formatter TERAS1: D[CONST 1] ROT[35. - 22.] ALU[DORQ] DEST[HOLD] NORM JUMP[KNYMTP] $ ;Add WRT CMD bit and start command. TERASE: D[CONST 3] ROT[35. - 29.] DEST[Q] NORM JUMP[TERAS1] $ ;ERASE A 3.75" GAP ON THE TAPE (get WFM and ERASE bits for formatter) KNYMTP: START-OUT NORM $ ;Give TP MR to clear mode, error status MAPF[TP.MR] D[MEM] DEST[Q] C-OUT PUSHJ[KNYGOA] $ ;Put command bits in Q and start formatter. START-OUT D[CONST 1] ROT[35. - 26.] DEST[IOD] NORM $ ;Clear all command bits except FORMATTER ENABLE. MAPF[TP.WF] ALU[-1] DEST[Q] LONG POPJ $ ;Put -1 in Q in case we are returning to TAPEMT. TAPERW: ;REWIND D[CONST 24] DEST[HOLD] NORM JUMP[KNYMTP] $ ;RWD AND GO BITS -- KNYGOA WILL DELETE THE GO BIT ! TAPEFR: ;SKIP FORWARD ONE RECORD. D[CONST 0] DEST[HOLD] NORM JUMP[KNYMTP] $ ;START A READ, BUT IGNORE THE DATA. TAPEBR: ;SKIP BACKWARD ONE RECORD. D[CONST 1] ROT[35. - 27.] DEST[HOLD] NORM JUMP[KNYMTP] $ ;JUST A READ BACKWARD, WITH THE DATA IGNORED. TPSETIND: ;Set industry compatable mode D[10 + TPMODE] DEST[Q] NORM $ ;Stupid A-MEM D[CONST 1] ROT[35.] ALU[DORQ] DEST[TPMODE] DEST-A-MEM JUMP[GOMAIN] $ ;Set appropriate bit and done TPSETDMP: ;Set PDP-10 Dump Mode D[10 + TPMODE] DEST[Q] NORM $ ;Stupid A-MEM D[CONST 1] ROT[35.] ALU[-D&Q] DEST[TPMODE] DEST-A-MEM JUMP[GOMAIN] $ ;Clear industry compatable mode and done. TPSETNK: ;Enter NRZI KLUGE mode. D[10 + TPMODE] DEST[Q] NORM $ ;Stupid A-MEM D[CONST 1] ROT[34.] ALU[DORQ] DEST[TPMODE] DEST-A-MEM JUMP[GOMAIN] $ ;Set appropriate bit and done TPCLRNK: ;Leave NRZI KLUGE mode. D[10 + TPMODE] DEST[Q] NORM $ ;Stupid A-MEM D[CONST 1] ROT[34.] ALU[-D&Q] DEST[TPMODE] DEST-A-MEM JUMP[GOMAIN] $ TAPERS: ;OPCODE 727 -- READ STATUS BITS FROM TAPE DRIVE. .DEFINE TSS[A B] [ ;MOVE BIT A OF AR TO BIT B OF Q. D[AR] ROT[1 + A] MASK[1] DEST[HOLD] NORM $ D[MEM] ROT[35. - B] ALU[DORQ] DEST[Q] NORM $ ] START-OUT ALU[0] DEST[IOD] NORM $ ;CLEAR THE MODE CTRL REGISTER. MAPF[TP.WM] START-OUT D[CONST 1] ROT[35. - 26.] DEST[IOD] C-OUT $ ;ENABLE THE FORMATTER. MAPF[TP.WF] START-IN ALU[0] DEST[Q] C800 $ ;READ STATUS BITS. MAPF[TP.RS] D[IOD] ALU[NOTD] DEST[AR] C800 $ ;NOW RE-ARRANGE THE BITS TSS[ 3 30. ] ;ON LINE TSS[ 11. 31. ] ;REWINDING TSS[ 4 32. ] ;FILE PROTECT TSS[ 12. 33. ] ;LOAD POINT TSS[ 10. 34. ] ;READY TSS[ 34. 35. ] ;END OF TAPE ALU[Q] DEST[MEMSTO] NORM COND[-MA-AC] LBJUMP[HIGHSMAIN] $ .PAIR UIOTRP[MUUO] $ TAPENR: ;730, AC/COUNT. READ WHOLE RECORD, STORING UP TO COUNT WORDS STARTING AT EFF ADR. ;SWAP AC AND IR, THEN DO TAPERX. D[IR] DEST[O_AC IR-ADR] ACSEL[AC] NORM JUMP[TAPERX] $ .PAIR UIOTRP[MUUO] $ TAPERX: ;732 - (AC) IS START ADDR., E IS # OF WORDS TO READ. NORM PUSHJ[KNYRGO] $ ;GET TAPE STARTED. ALU[AC] ACSEL[AC] DEST[4] DEST-A-MEM PUSHJ[TRP2] NORM $ ;READ REC. D[AR] ROT[16.] -OBUS<0 JUMP[TNRP3] $ ;Was record longer than word count ? ;Jump unless FIFO RDY FOR BUF is on, indicating ; that tape supplied more bytes after count ran out. D[CONST 44] ROT[30.] ALU[DORQ] DEST[Q] NORM $ ;YES, SET BIT 3. TNRP3: ALU[Q] DEST[AC] ACSEL[AC] JPOP[GOMAIN] NORM $ ;NO, NOT TOO LONG. ;MOVE STATUS INTO AC. UTAPWR: UIOTRP[MUUO] $ TAPEWR: ;731, AC/ADR, E/+COUNT. WRITE RECORD OF +COUNT ; WORDS, DATA FROM ADR. ;SET AC:=0 IF OPERATION COMPLETED SUCCESSFULLY. ; SET AC:= + HIGHEST ADR READ IF REACHED ; EOT DURING OPERATION (CURRENTLY THIS IS THE ONLY ; ERROR CONDITION.) OPERATION IS COMPLETED EVEN ; IF EOT IS PASSED. D[CONST 10.] DEST[7] DEST-A-MEM NORM $ ;SET UP ERROR RETRY COUNT. TWRTRY: NORM PUSHJ[DCINIT] $ ;Init. the data channel D[10 + TPMODE] ROT[1] MASK[1] DEST[AR] NORM $ ;Get the 32-bit mode flag. D[AR] ROT[35. - 29.] DEST[Q] NORM $ ;Position it for the hardware. START-OUT D[CONST 1] ROT[35. - 28.] ALU[DORQ] DEST[IOD] NORM $ ;Set the OUT bit. MAPF[TP.WM] D[CONST 1] ROT[35. - 22.] DEST[Q] PUSHJ[KNYGOA] $ ;Issue WRITE command to formatter. ALU[AC] DEST[4] DEST-A-MEM NORM PUSHJ[STRTDC] $ ;Get word count and start the channel. D[MEM] ROT[32.] -OBUS<0 JUMP[TWERR] $ ;Test HARD ERR. ALU[0] DEST[AC] NORM $ ;We return 0 in AC if no EOT. D[MEM] ROT[34.] C550 OBUS<0 JUMP[GOMAIN] $ ;If no EOT seen, all done. D[CONST 60] ROT[35. - 5] ALU[DORAC] DEST[AC] NORM JUMP[GOMAIN] $ ;Turn on bit 0 to indicate EOT seen during operation. TWERR: ;;Error occurred during write. Backspace, erase gap, and retry. NORM PUSHJ[KNYRS1] $ ;Blast the tape formatter and drive D[17] ALU[D-1] DEST[Q] C550 -OBUS<0 JUMP[TWER1] $ ;See if we have had to many retry's already... D[CONST 50] ROT[30.] DEST[AC] JUMP[GOMAIN] $ ;Hopeless. Give error return to prgm. TWER1: ALU[Q] DEST[7] DEST-A-MEM NORM PUSHJ[TAPEBR] $ ;Start a BACKSPACE RECORD command. START-IN NORM PUSHJ[FMNBWT] $ ;Wait for completion. PUSHJ[TERASE] $ ;Start erasing a 3.75" gap. START-IN NORM PUSHJ[FMNBWT] $ ;Wait for completion. NORM JUMP[TWRTRY] $ ;Start write op again. ;BOOTSTRAP LOADER FOR MACROCODE. .ORG[5000] MBOOT: JPOP[. + 1] $ ;The . + 1 is to make the lights look familiar for the operator... JUMP[MBOOTA] $ ;MBOOTA takes us to MBOOTH, whether or not that is in high u-mem. .REPEAT XUCODE [ ;If 8K u-mem, put this code in upper 4K AREA50 = . .USE[HIGHMEM] ] ;XUCODE MBOOTH: D[CONST 7] DEST[DEV-ADR] PUSHJ[KNYCLR] $ ;RESET TAPE CTRL ALU[0] DEST[HI-ABS-MA] PUSHJ[CCLR] NORM $ D[CONST 1] ROT[18.] DEST[HI-ABS-MA] PUSHJ[CCLR] NORM $ D[CONST 7] DEST[DEV-ADR] CYLEN[LONG] PUSHJ[KNYRGO] $ ;SELECT DEVICE 7, START READ. NORM PUSHJ[KNYWAIT] $ MAPF[TP.RC] START-IN D[IOD] ALU[NOTD] DEST[HOLD] C800 PUSHJ[MBTBYX] $ ;Read 1st byte of new record. ALU[0] DEST[MA HI-ABS-MA] NORM JUMP[P2A] $ ;Clear high-order MA and enter reading loop. P2: D[MA] ALU[D+1] DEST[MA] PUSHJ[MBTBYTE] NORM $ P2A: D[MEM] ROT[34] DEST[Q] PUSHJ[MBTBYTE] NORM $ D[MEM] ROT[24] ALU[DORQ] DEST[Q] PUSHJ[MBTBYTE] NORM $ D[MEM] ROT[14] ALU[DORQ] DEST[Q] PUSHJ[MBTBYTE] NORM $ D[MEM] ROT[4] ALU[DORQ] DEST[Q] PUSHJ[MBTBYTE] NORM $ D[MEM] MASK[4] ALU[DORQ] DEST[MEMSTO] NORM JUMP[P2] $ CCLR: ALU[0] DEST[MA] NORM $ ALU[0] DEST[MEMSTO] NORM $ D[MA] ALU[D+1] DEST[MA] NORM $ D[MA] MASK[18.] COND[-OBUS=0] JUMP[. - 2] C600 $ POPJ NORM $ MBTBYTE: START-IN D[CONST 35] ROT[1] LLOAD NORM $ ;Ask tape for a byte and status thereof ;Set loop counter to do timeout ;(TIMEOUT ABOUT 78 USEC) MBTBY1: MAPF[TP.RC] D[IOD] DEST[HOLD] C800 LOOP[MBTBY2] $ ;Read byte and status. Byte comes complemented. ;Result is put in HOLD to avoid synchronizer problems ;Do timeout check and branch if still waiting START-IN NORM PUSHJ[MBTCHECK] $ ;Byte wasn't ready in time. Go find out why PUSHJ[KNYRGO] $ ;START NEXT RECORD. NORM PUSHJ[KNYWAIT] $ MAPF[TP.RC] START-IN D[IOD] ALU[NOTD] DEST[HOLD] C800 PUSHJ[MBTBYX] $ ;Read 1st byte of new record. NORM JPOP[P2A] $ ;Go for another record ; --- MBTBY2: START-IN D[MEM] ROT[26.] -OBUS<0 C550 JUMP[MBTBY1] $ ;Check for byte ready (this is a two instruction loop) ;Start getting byte and status again in case we have ; to loop START-IN MAPF[TP.RC] D[IOD] ALU[NOTD] DEST[HOLD] C800 $ ;READ THE DATA AGAIN (NOW THAT IT'S STABLE !) MBTBYX: MAPF[1] D[MEM] MASK[10] DEST[HOLD] C550 POPJ $ ;MAPF[1] clears byte ready ;Extract data byte from other status information ; --- KNYWAIT: ;Wait for first byte of read data (BOOTSTRAP mode only) START-IN SHORT $ MAPF[1] START-IN D[CONST 77] ROT[12.] DEST[AR] NORM $ ;Clear read data ready flag KNYW1: MAPF[TP.RC] D[IOD] DEST[HOLD] C600 $ START-IN D[MEM] ROT[26.] OBUS<0 POPJ C550 $ ;Return if READ DATA RDY is now on. START-IN D[AR] ALU[D-1] DEST[AR] C550 -OBUS=0 JUMP[KNYW1] $ NORM POPJ $ MBTCHECK: START-IN NORM PUSHJ[FMNBWT] $ ;WAIT FOR FORMATTER IDLE. D[MEM] ROT[32.] C550 -OBUS<0 JUMP[MBTERR] $ ;CHECK FOR ERROR STATUS. D[MEM] ROT[33.] C550 OBUS<0 POPJ $ ;IF END OF FILE NOT SEEN, RETURN FOR MORE, ELSE DONE. ALU[0] DEST[Q] NORM $ ;CLEAR LIGHTS TO INDICATE NO ERRORS. MBTDNX: START-OUT ALU[0] DEST[DEV-ADR] JPOP[. + 1] $ ;Setup to display code in lights START-OUT MAPF[2] ALU[Q] JPOP[. + 1] $ ;LOAD LIGHTS FROM Q, CLR SW FF'S D1: MAPF[4] START-IN $ ;CHECK START AND CONT SWITCHES. RD NEXT FILE ON CONT MAPF[4] D[IOD] DEST[AR] $ D[AR] ROT[5] MASK[2] DEST[AR] COND[OBUS=0] JUMP[D1] CYLEN[LONG] $ ;WAIT FOR A SWITCH. D[AR] MASK[1] COND[-OBUS=0] JUMP[GOMSTART] C550 $ ; ... START MAIN MICROCODE ON START SWITCH. START-OUT NORM $ ;CLEAR SWITCH FF'S MAPF[4] JPOP[MBOOTH] CYLEN[LONG] $ GOMSTART: ;Branch to MSTART GETADR[MSTART] JUMP[GOLOW] $ MBTERR: D[CONST 0] ALU[NOTD] DEST[Q] JUMP[MBTDNX] $ ; --- .ORG[2150] JUMP[.] $ ;Hang if any interrupts from device 7 occur. .USE[OTHER] ;RETURN TO OLD LOC. CTR. MBOOTA: GETADR[MBOOTH] JUMP[GOHIGH] $